<template>
  <div class="control-section component-gap">
    <h3>✈️ 轨迹规划与栅格地图</h3>
    
    <!-- 地图显示区域 -->
    <div class="map-module">
      <h4>栅格地图可视化</h4>
      <div class="map-container">
        <canvas 
          ref="mapCanvas" 
          :width="canvasSize" 
          :height="canvasSize"
          @click="handleMapClick"
          @mousemove="handleMapHover"
          class="map-canvas"
        ></canvas>
        
        <!-- 地图控制工具栏 -->
        <div class="map-controls">
          <button 
            @click="centerMap" 
            class="btn btn-map-control"
            :disabled="!isConnected"
          >
            🎯 居中地图
          </button>
          <button 
            @click="toggleGrid" 
            class="btn btn-map-control"
            :class="{ 'btn-active': showGrid }"
          >
            {{ showGrid ? '📏 隐藏网格' : '📏 显示网格' }}
          </button>
          <button 
            @click="clearAllWaypoints" 
            class="btn btn-map-control btn-danger"
            :disabled="!isConnected || trajectory.poses.length === 0"
          >
            🗑️ 清空路径
          </button>
          <button 
            @click="refreshGridMap" 
            class="btn btn-map-control"
            :disabled="!isConnected"
          >
            🔄 刷新地图
          </button>
        </div>
        
        <!-- 地图状态信息 -->
        <div class="map-status">
          <div class="status-item">
            <label>地图中心:</label>
            <span>({{ mapCenter.x.toFixed(1) }}, {{ mapCenter.y.toFixed(1) }})</span>
          </div>
          <div class="status-item">
            <label>缩放级别:</label>
            <span>{{ zoomLevel.toFixed(1) }}x</span>
          </div>
          <div class="status-item">
            <label>路径点数量:</label>
            <span>{{ trajectory.poses.length }}</span>
          </div>
          <div class="status-item">
            <label>障碍物数量:</label>
            <span>{{ obstacleCount }}</span>
          </div>
        </div>
      </div>
    </div>

    <!-- 路径点管理 -->
    <div class="waypoint-module">
      <h4>路径点设置（{{ trajectory.poses.length }} 个点）</h4>
      <div class="waypoint-controls">
        <!-- 添加路径点表单 -->
        <div class="add-waypoint-form">
          <div class="form-fields">
            <div class="form-field">
              <label>X坐标 (m):</label>
              <input 
                type="number" 
                v-model.number="newWaypoint.x" 
                class="waypoint-input"
                step="0.1"
                :disabled="!isConnected"
              >
            </div>
            <div class="form-field">
              <label>Y坐标 (m):</label>
              <input 
                type="number" 
                v-model.number="newWaypoint.y" 
                class="waypoint-input"
                step="0.1"
                :disabled="!isConnected"
              >
            </div>
            <div class="form-field">
              <label>Z坐标 (m):</label>
              <input 
                type="number" 
                v-model.number="newWaypoint.z" 
                class="waypoint-input"
                step="0.1"
                min="0.5"
                :disabled="!isConnected"
              >
            </div>
            <button 
              @click="addWaypoint" 
              class="btn btn-add"
              :disabled="!isConnected || !isWaypointValid()"
            >
              ➕ 添加路径点
            </button>
            <button 
              @click="addCurrentPosition" 
              class="btn btn-current"
              :disabled="!isConnected || !currentPosition"
            >
              📍 当前位置
            </button>
          </div>
        </div>
        
        <!-- 路径点列表 -->
        <div class="waypoint-list" v-if="trajectory.poses.length > 0">
          <div class="list-header">
            <div class="col-index">#</div>
            <div class="col-x">X (m)</div>
            <div class="col-y">Y (m)</div>
            <div class="col-z">Z (m)</div>
            <div class="col-action">操作</div>
          </div>
          <div 
            v-for="(pose, index) in trajectory.poses" 
            :key="index" 
            class="list-row"
            :class="{ 'active': hoveredWaypoint === index }"
            @mouseenter="hoveredWaypoint = index"
            @mouseleave="hoveredWaypoint = -1"
          >
            <div class="col-index">{{ index + 1 }}</div>
            <div class="col-x">{{ pose.pose.position.x.toFixed(2) }}</div>
            <div class="col-y">{{ pose.pose.position.y.toFixed(2) }}</div>
            <div class="col-z">{{ pose.pose.position.z.toFixed(2) }}</div>
            <div class="col-action">
              <button 
                @click="removeWaypoint(index)" 
                class="btn btn-remove"
                :disabled="!isConnected"
              >
                ×
              </button>
              <button 
                @click="centerOnWaypoint(index)" 
                class="btn btn-center"
                :disabled="!isConnected"
              >
                🎯
              </button>
            </div>
          </div>
        </div>
        <div class="empty-waypoints" v-else>
          🗺️ 暂无路径点，点击地图或使用表单添加路径点...
        </div>
        
        <!-- 路径点批量操作 -->
        <div class="waypoint-batch-actions">
          <button 
            @click="reverseWaypoints" 
            class="btn btn-reverse"
            :disabled="!isConnected || trajectory.poses.length < 2"
          >
            ↔️ 反转路径顺序
          </button>
          <button 
            @click="optimizePath" 
            class="btn btn-optimize"
            :disabled="!isConnected || trajectory.poses.length < 3"
          >
            🔄 优化路径
          </button>
          <button 
            @click="exportWaypoints" 
            class="btn btn-export"
            :disabled="!isConnected || trajectory.poses.length === 0"
          >
            📤 导出路径
          </button>
        </div>
      </div>
    </div>

    <!-- 轨迹发送控制 -->
    <div class="trajectory-send-module">
      <div class="send-controls">
        <div class="trajectory-options">
          <label class="option-label">
            <input 
              type="checkbox" 
              v-model="trajectoryOptions.loop" 
              :disabled="!isConnected"
            >
            循环执行轨迹
          </label>
          <label class="option-label">
            <input 
              type="checkbox" 
              v-model="trajectoryOptions.velocity_control" 
              :disabled="!isConnected"
            >
            速度控制模式
          </label>
        </div>
        
        <div class="trajectory-actions">
          <button 
            @click="publishTrajectory" 
            class="btn btn-publish"
            :disabled="!isConnected || trajectory.poses.length < 2"
          >
            📤 发布轨迹
          </button>
          <button 
            @click="executeTrajectory" 
            class="btn btn-execute"
            :disabled="!isConnected || trajectory.poses.length < 2"
          >
            🚀 执行轨迹
          </button>
          <button 
            @click="stopTrajectory" 
            class="btn btn-stop"
            :disabled="!isConnected"
          >
            ⏹️ 停止轨迹
          </button>
        </div>
      </div>
    </div>

    <!-- 轨迹执行状态 -->
    <div class="execution-status">
      <h4>轨迹执行状态</h4>
      <div class="status-info">
        <div class="status-item">
          <label>轨迹状态:</label>
          <span :class="getStatusClass(trajectoryStatus)">
            {{ getStatusText(trajectoryStatus) }}
          </span>
        </div>
        <div class="status-item">
          <label>已发布路径点:</label>
          <span>{{ publishedWaypoints }}</span>
        </div>
        <div class="status-item">
          <label>执行进度:</label>
          <span>{{ executionProgress }}%</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
// 修复：添加ROSLIB导入
import ROSLIB from 'roslib';

export default {
  name: 'TrajectoryPlanning',
  props: {
    isConnected: {
      type: Boolean,
      required: true,
      default: false
    },
    trajectory: {
      type: Object,
      required: true,
      default: () => ({
        header: { 
          seq: 0,
          stamp: { secs: 0, nsecs: 0 },
          frame_id: 'world' 
        },
        poses: []
      })
    },
    currentPosition: {
      type: Object,
      default: () => ({ x: 0, y: 0, z: 0 })
    }
  },
  data() {
    return {
      canvasSize: 500,
      mapCenter: { x: 0, y: 0 },
      zoomLevel: 1.0,
      showGrid: true,
      hoveredWaypoint: -1,
      mousePos: { x: 0, y: 0 },
      
      newWaypoint: {
        x: 0,
        y: 0,
        z: 1.5
      },
      
      trajectoryOptions: {
        loop: false,
        velocity_control: false
      },
      
      trajectoryStatus: 'idle',
      publishedWaypoints: 0,
      executionProgress: 0,
      
      gridMapData: {
        points: [],
        resolution: 0.1,
        width: 0,
        height: 0,
        origin: { x: 0, y: 0, z: 0 }
      },
      obstacleCount: 0,
      
      gridMapSubscriber: null,
      
      ctx: null,
      animationFrame: null
    };
  },
  mounted() {
    this.initMap();
    this.startAnimation();
  },
  beforeUnmount() {
    if (this.animationFrame) {
      cancelAnimationFrame(this.animationFrame);
    }
    if (this.gridMapSubscriber) {
      this.gridMapSubscriber.unsubscribe();
    }
  },
  watch: {
    isConnected: {
      handler(newVal) {
        if (newVal) {
          this.setupGridMapSubscription();
        } else {
          if (this.gridMapSubscriber) {
            this.gridMapSubscriber.unsubscribe();
            this.gridMapSubscriber = null;
          }
        }
      },
      immediate: true
    }
  },
  methods: {
    initMap() {
      const canvas = this.$refs.mapCanvas;
      this.ctx = canvas.getContext('2d');
      this.centerMap();
    },
    
    setupGridMapSubscription() {
      if (!this.isConnected || !this.$parent.ros) {
        return;
      }
      
      this.gridMapSubscriber = new ROSLIB.Topic({
        ros: this.$parent.ros,
        name: '/uav1_ego_planner_node/grid_map/occupancy_inflate',
        messageType: 'sensor_msgs/PointCloud2'
      });
      
      this.gridMapSubscriber.subscribe(this.handleGridMapMessage.bind(this));
      this.$emit('log-message', '已订阅栅格地图话题');
    },
    
    handleGridMapMessage(message) {
      try {
        const points = this.parsePointCloud2(message);
        this.gridMapData.points = points;
        this.obstacleCount = points.length;
        
        this.gridMapData.resolution = 0.1;
        this.gridMapData.origin = { x: -10, y: -10, z: 0 };
        
        this.$emit('log-message', `收到栅格地图数据: ${points.length}个障碍物点`);
      } catch (error) {
        console.error('解析栅格地图数据失败:', error);
        this.$emit('log-message', '❌ 解析栅格地图数据失败');
      }
    },
    
    // 修复：删除未使用的row_step解构
    parsePointCloud2(message) {
      const points = [];
      const { data, fields, point_step } = message;
      
      let xOffset = -1, yOffset = -1, zOffset = -1;
      
      fields.forEach(field => {
        if (field.name === 'x') xOffset = field.offset;
        if (field.name === 'y') yOffset = field.offset;
        if (field.name === 'z') zOffset = field.offset;
      });
      
      if (xOffset === -1 || yOffset === -1 || zOffset === -1) {
        throw new Error('找不到坐标字段');
      }
      
      for (let i = 0; i < data.length; i += point_step) {
        const x = this.readFloat32(data, i + xOffset);
        const y = this.readFloat32(data, i + yOffset);
        const z = this.readFloat32(data, i + zOffset);
        
        points.push({ x, y, z });
      }
      
      return points;
    },
    
    readFloat32(data, offset) {
      const view = new DataView(data.buffer, data.byteOffset + offset, 4);
      return view.getFloat32(0, true);
    },
    
    refreshGridMap() {
      this.gridMapData.points = [];
      this.obstacleCount = 0;
      this.$emit('log-message', '刷新栅格地图数据');
    },
    
    startAnimation() {
      const animate = () => {
        this.drawMap();
        this.animationFrame = requestAnimationFrame(animate);
      };
      animate();
    },
    
    drawMap() {
      const { ctx, canvasSize, mapCenter, zoomLevel, showGrid } = this;
      
      ctx.clearRect(0, 0, canvasSize, canvasSize);
      
      ctx.fillStyle = '#1a1a2e';
      ctx.fillRect(0, 0, canvasSize, canvasSize);
      
      const scale = (canvasSize / 20) * zoomLevel;
      const offsetX = canvasSize / 2 - mapCenter.x * scale;
      const offsetY = canvasSize / 2 - mapCenter.y * scale;
      
      if (showGrid) {
        this.drawGrid(ctx, scale, offsetX, offsetY);
      }
      
      this.drawAxes(ctx, scale, offsetX, offsetY);
      
      this.drawObstacles(ctx, scale, offsetX, offsetY);
      
      this.drawTrajectory(ctx, scale, offsetX, offsetY);
      
      this.drawUAVPosition(ctx, scale, offsetX, offsetY);
      
      this.drawMousePosition(ctx);
    },
    
    drawGrid(ctx, scale, offsetX, offsetY) {
      ctx.strokeStyle = '#2d3047';
      ctx.lineWidth = 1;
      
      const gridSize = 1;
      const startX = -10;
      const startY = -10;
      const endX = 10;
      const endY = 10;
      
      for (let x = startX; x <= endX; x += gridSize) {
        const screenX = x * scale + offsetX;
        ctx.beginPath();
        ctx.moveTo(screenX, 0);
        ctx.lineTo(screenX, this.canvasSize);
        ctx.stroke();
      }
      
      for (let y = startY; y <= endY; y += gridSize) {
        const screenY = y * scale + offsetY;
        ctx.beginPath();
        ctx.moveTo(0, screenY);
        ctx.lineTo(this.canvasSize, screenY);
        ctx.stroke();
      }
    },
    
    drawAxes(ctx, scale, offsetX, offsetY) {
      ctx.strokeStyle = '#4cc9f0';
      ctx.lineWidth = 2;
      
      ctx.beginPath();
      ctx.moveTo(0, offsetY);
      ctx.lineTo(this.canvasSize, offsetY);
      ctx.stroke();
      
      ctx.beginPath();
      ctx.moveTo(offsetX, 0);
      ctx.lineTo(offsetX, this.canvasSize);
      ctx.stroke();
      
      ctx.fillStyle = '#4cc9f0';
      ctx.font = '12px Arial';
      ctx.fillText('X', this.canvasSize - 10, offsetY - 5);
      ctx.fillText('Y', offsetX + 5, 15);
    },
    
    // 修复：添加this访问zoomLevel
    drawObstacles(ctx, scale, offsetX, offsetY) {
      const { gridMapData } = this;
      
      if (!gridMapData.points || gridMapData.points.length === 0) {
        ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
        ctx.font = '14px Arial';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText('等待栅格地图数据...', this.canvasSize / 2, this.canvasSize / 2);
        return;
      }
      
      ctx.fillStyle = 'rgba(231, 76, 60, 0.8)';
      
      gridMapData.points.forEach(point => {
        const screenX = point.x * scale + offsetX;
        const screenY = point.y * scale + offsetY;
        const pointSize = 2 * this.zoomLevel; // 修复：添加this.
        
        ctx.beginPath();
        ctx.arc(screenX, screenY, pointSize, 0, Math.PI * 2);
        ctx.fill();
      });
    },
    
    drawTrajectory(ctx, scale, offsetX, offsetY) {
      const { trajectory, hoveredWaypoint, trajectoryStatus } = this;
      
      if (trajectory.poses.length === 0) return;
      
      ctx.strokeStyle = trajectoryStatus === 'executing' ? '#f39c12' : '#3498db';
      ctx.lineWidth = 3;
      ctx.setLineDash([]);
      ctx.beginPath();
      
      trajectory.poses.forEach((pose, index) => {
        const x = pose.pose.position.x * scale + offsetX;
        const y = pose.pose.position.y * scale + offsetY;
        
        if (index === 0) {
          ctx.moveTo(x, y);
        } else {
          ctx.lineTo(x, y);
        }
      });
      
      ctx.stroke();
      
      trajectory.poses.forEach((pose, index) => {
        const x = pose.pose.position.x * scale + offsetX;
        const y = pose.pose.position.y * scale + offsetY;
        
        ctx.fillStyle = index === hoveredWaypoint ? '#f39c12' : '#2ecc71';
        ctx.beginPath();
        ctx.arc(x, y, 6, 0, Math.PI * 2);
        ctx.fill();
        
        ctx.fillStyle = 'white';
        ctx.font = '10px Arial';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText((index + 1).toString(), x, y);
      });
    },
    
    drawUAVPosition(ctx, scale, offsetX, offsetY) {
      const { currentPosition } = this;
      
      if (!currentPosition || (currentPosition.x === 0 && currentPosition.y === 0)) return;
      
      const x = currentPosition.x * scale + offsetX;
      const y = currentPosition.y * scale + offsetY;
      
      ctx.fillStyle = '#9b59b6';
      ctx.beginPath();
      ctx.moveTo(x, y - 8);
      ctx.lineTo(x - 6, y + 4);
      ctx.lineTo(x + 6, y + 4);
      ctx.closePath();
      ctx.fill();
      
      ctx.strokeStyle = '#9b59b6';
      ctx.lineWidth = 2;
      ctx.beginPath();
      ctx.moveTo(x, y + 4);
      ctx.lineTo(x, y + 12);
      ctx.stroke();
      
      ctx.fillStyle = '#9b59b6';
      ctx.font = '10px Arial';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'bottom';
      ctx.fillText('UAV', x, y - 10);
    },
    
    drawMousePosition(ctx) {
      const { mousePos } = this;
      
      const worldPos = this.screenToWorld(mousePos.x, mousePos.y);
      ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
      ctx.font = '12px Arial';
      ctx.textAlign = 'left';
      ctx.textBaseline = 'top';
      ctx.fillText(`(${worldPos.x.toFixed(1)}, ${worldPos.y.toFixed(1)})`, 10, 10);
    },
    
    screenToWorld(screenX, screenY) {
      const { canvasSize, mapCenter, zoomLevel } = this;
      const scale = (canvasSize / 20) * zoomLevel;
      const offsetX = canvasSize / 2 - mapCenter.x * scale;
      const offsetY = canvasSize / 2 - mapCenter.y * scale;
      
      return {
        x: (screenX - offsetX) / scale,
        y: (screenY - offsetY) / scale
      };
    },
    
    worldToScreen(worldX, worldY) {
      const { canvasSize, mapCenter, zoomLevel } = this;
      const scale = (canvasSize / 20) * zoomLevel;
      const offsetX = canvasSize / 2 - mapCenter.x * scale;
      const offsetY = canvasSize / 2 - mapCenter.y * scale;
      
      return {
        x: worldX * scale + offsetX,
        y: worldY * scale + offsetY
      };
    },
    
    handleMapClick(event) {
      const rect = this.$refs.mapCanvas.getBoundingClientRect();
      const x = event.clientX - rect.left;
      const y = event.clientY - rect.top;
      
      const worldPos = this.screenToWorld(x, y);
      this.newWaypoint.x = Number(worldPos.x.toFixed(2));
      this.newWaypoint.y = Number(worldPos.y.toFixed(2));
      
      this.addWaypoint();
    },
    
    handleMapHover(event) {
      const rect = this.$refs.mapCanvas.getBoundingClientRect();
      this.mousePos.x = event.clientX - rect.left;
      this.mousePos.y = event.clientY - rect.top;
    },
    
    centerMap() {
      this.mapCenter = { x: 0, y: 0 };
      this.zoomLevel = 1.0;
    },
    
    toggleGrid() {
      this.showGrid = !this.showGrid;
    },
    
    centerOnWaypoint(index) {
      if (index >= 0 && index < this.trajectory.poses.length) {
        const pose = this.trajectory.poses[index];
        this.mapCenter = {
          x: pose.pose.position.x,
          y: pose.pose.position.y
        };
      }
    },
    
    isWaypointValid() {
      return (
        !isNaN(this.newWaypoint.x) &&
        !isNaN(this.newWaypoint.y) &&
        !isNaN(this.newWaypoint.z) &&
        this.newWaypoint.z >= 0.5
      );
    },
    
    addWaypoint() {
      if (!this.isWaypointValid()) {
        alert('路径点无效！请检查坐标值（Z坐标≥0.5m）');
        return;
      }
      
      const newPose = {
        header: { frame_id: 'world' },
        pose: {
          position: {
            x: Number(this.newWaypoint.x.toFixed(2)),
            y: Number(this.newWaypoint.y.toFixed(2)),
            z: Number(this.newWaypoint.z.toFixed(2))
          },
          orientation: { x: 0, y: 0, z: 0, w: 1 }
        }
      };
      
      const updatedPoses = [...this.trajectory.poses, newPose];
      this.updateTrajectory(updatedPoses);
    },
    
    addCurrentPosition() {
      if (!this.currentPosition) return;
      
      this.newWaypoint.x = Number(this.currentPosition.x.toFixed(2));
      this.newWaypoint.y = Number(this.currentPosition.y.toFixed(2));
      this.newWaypoint.z = Number(Math.max(this.currentPosition.z, 1.5).toFixed(2));
      
      this.addWaypoint();
    },
    
    removeWaypoint(index) {
      const updatedPoses = this.trajectory.poses.filter((_, i) => i !== index);
      this.updateTrajectory(updatedPoses);
    },
    
    clearAllWaypoints() {
      if (confirm('确定要清空所有路径点吗？')) {
        this.updateTrajectory([]);
        this.trajectoryStatus = 'idle';
        this.publishedWaypoints = 0;
        this.executionProgress = 0;
      }
    },
    
    reverseWaypoints() {
      const reversedPoses = [...this.trajectory.poses].reverse();
      this.updateTrajectory(reversedPoses);
    },
    
    optimizePath() {
      if (this.trajectory.poses.length < 3) return;
      
      const optimized = [...this.trajectory.poses];
      this.updateTrajectory(optimized);
      
      this.$emit('log-message', '路径已优化');
    },
    
    exportWaypoints() {
      const waypoints = this.trajectory.poses.map(pose => ({
        x: pose.pose.position.x,
        y: pose.pose.position.y,
        z: pose.pose.position.z
      }));
      
      const dataStr = JSON.stringify(waypoints, null, 2);
      const dataBlob = new Blob([dataStr], { type: 'application/json' });
      
      const link = document.createElement('a');
      link.href = URL.createObjectURL(dataBlob);
      link.download = `trajectory_${new Date().toISOString().split('T')[0]}.json`;
      link.click();
    },
    
    updateTrajectory(poses) {
      this.$emit('update:trajectory', {
        ...this.trajectory,
        poses: poses
      });
    },
    
    publishTrajectory() {
      if (this.trajectory.poses.length < 2) {
        alert('至少需要2个路径点才能发布轨迹！');
        return;
      }
      
      const now = new Date();
      const secs = Math.floor(now.getTime() / 1000);
      const nsecs = (now.getTime() % 1000) * 1000000;
      
      const trajectoryToSend = {
        ...this.trajectory,
        header: {
          ...this.trajectory.header,
          frame_id: 'world',
          stamp: { secs: secs, nsecs: nsecs }
        }
      };
      
      this.$emit('publish-trajectory', trajectoryToSend);
      
      this.trajectoryStatus = 'published';
      this.publishedWaypoints = trajectoryToSend.poses.length;
      this.$emit('log-message', `📤 已发布轨迹，包含 ${this.publishedWaypoints} 个路径点`);
    },
    
    executeTrajectory() {
      if (this.trajectory.poses.length < 2) {
        alert('至少需要2个路径点才能执行轨迹！');
        return;
      }
      
      this.$emit('execute-trajectory', {
        options: this.trajectoryOptions
      });
      
      this.trajectoryStatus = 'executing';
      this.executionProgress = 0;
      this.$emit('log-message', '🚀 开始执行轨迹');
      
      this.simulateExecutionProgress();
    },
    
    stopTrajectory() {
      this.$emit('stop-trajectory');
      
      this.trajectoryStatus = 'stopped';
      this.executionProgress = 0;
      this.$emit('log-message', '⏹️ 停止轨迹执行');
    },
    
    simulateExecutionProgress() {
      if (this.trajectoryStatus !== 'executing') return;
      
      const interval = setInterval(() => {
        if (this.trajectoryStatus !== 'executing') {
          clearInterval(interval);
          return;
        }
        
        this.executionProgress += 5;
        if (this.executionProgress >= 100) {
          this.executionProgress = 100;
          this.trajectoryStatus = 'completed';
          this.$emit('log-message', '✅ 轨迹执行完成');
          clearInterval(interval);
        }
      }, 500);
    },
    
    getStatusClass(status) {
      const classes = {
        idle: 'status-idle',
        published: 'status-published',
        executing: 'status-executing',
        completed: 'status-completed',
        stopped: 'status-stopped'
      };
      return classes[status] || 'status-idle';
    },
    
    getStatusText(status) {
      const texts = {
        idle: '待发布',
        published: '已发布',
        executing: '执行中',
        completed: '已完成',
        stopped: '已停止'
      };
      return texts[status] || '未知状态';
    }
  },
  emits: ['publish-trajectory', 'execute-trajectory', 'stop-trajectory', 'update:trajectory', 'log-message']
};
</script>

<style scoped>
.control-section {
  margin-bottom: 25px;
}

.control-section h3 {
  margin: 0 0 20px 0;
  color: #2c3e50;
  font-size: 18px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.map-module {
  margin-bottom: 20px;
  padding: 15px;
  background: #f8f9fa;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.map-module h4 {
  margin: 0 0 12px 0;
  color: #2c3e50;
  font-size: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.map-container {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.map-canvas {
  border: 2px solid #34495e;
  border-radius: 6px;
  background: #1a1a2e;
  cursor: crosshair;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}

.map-controls {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.btn-map-control {
  background: #34495e;
  color: white;
  padding: 6px 12px;
  font-size: 12px;
}

.btn-map-control.btn-active {
  background: #3498db;
}

.btn-map-control.btn-danger {
  background: #e74c3c;
}

.map-status {
  display: flex;
  gap: 20px;
  padding: 10px;
  background: white;
  border-radius: 6px;
  border: 1px solid #e0e0e0;
  flex-wrap: wrap;
}

.status-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
}

.status-item label {
  font-weight: 600;
  color: #7f8c8d;
}

.status-item span {
  color: #2c3e50;
  font-weight: 500;
}

.waypoint-module {
  margin-bottom: 20px;
  padding: 15px;
  background: #f8f9fa;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.waypoint-module h4 {
  margin: 0 0 12px 0;
  color: #2c3e50;
  font-size: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.waypoint-controls {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.add-waypoint-form {
  padding: 10px 0;
}

.form-fields {
  display: flex;
  gap: 15px;
  align-items: flex-end;
  flex-wrap: wrap;
}

.form-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 120px;
}

.form-field label {
  font-weight: 600;
  color: #2c3e50;
  font-size: 14px;
}

.waypoint-input {
  padding: 8px 12px;
  border: 2px solid #e0e0e0;
  border-radius: 4px;
  font-size: 14px;
  color: #2c3e50;
}

.waypoint-list {
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid #e0e0e0;
  max-height: 300px;
  overflow-y: auto;
}

.list-header {
  display: flex;
  background: #2c3e50;
  color: white;
  font-weight: bold;
  position: sticky;
  top: 0;
}

.list-row {
  display: flex;
  background: white;
  border-bottom: 1px solid #e0e0e0;
  transition: background 0.3s;
}

.list-row:hover,
.list-row.active {
  background: #f1f2f6;
}

.col-index { width: 50px; padding: 10px; text-align: center; }
.col-x { flex: 1; padding: 10px; }
.col-y { flex: 1; padding: 10px; }
.col-z { flex: 1; padding: 10px; }
.col-action { width: 100px; padding: 10px; text-align: center; display: flex; gap: 5px; justify-content: center; }

.empty-waypoints {
  padding: 30px;
  text-align: center;
  color: #7f8c8d;
  font-size: 14px;
  background: white;
  border-radius: 6px;
  border: 1px dashed #e0e0e0;
}

.waypoint-batch-actions {
  display: flex;
  gap: 10px;
  padding: 5px 0;
  flex-wrap: wrap;
}

.trajectory-send-module {
  padding: 15px;
  background: #f8f9fa;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.send-controls {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.trajectory-options {
  display: flex;
  gap: 20px;
}

.option-label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  color: #2c3e50;
  cursor: pointer;
}

.trajectory-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.execution-status {
  padding: 15px;
  background: #f8f9fa;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.execution-status h4 {
  margin: 0 0 12px 0;
  color: #2c3e50;
  font-size: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.status-info {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
}

.status-published {
  color: #3498db;
  font-weight: bold;
}

.status-executing {
  color: #f39c12;
  font-weight: bold;
}

.status-completed {
  color: #27ae60;
  font-weight: bold;
}

.status-stopped {
  color: #e74c3c;
  font-weight: bold;
}

.status-idle {
  color: #7f8c8d;
  font-weight: bold;
}

.btn {
  padding: 8px 16px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  transition: all 0.3s ease;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

.btn:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.btn-add { background: #2ecc71; color: white; }
.btn-current { background: #9b59b6; color: white; }
.btn-remove { 
  background: #e74c3c; 
  color: white; 
  width: 28px; 
  height: 28px; 
  padding: 0; 
  border-radius: 50%; 
  font-size: 16px; 
  display: flex;
  align-items: center;
  justify-content: center;
}
.btn-center {
  background: #3498db;
  color: white;
  width: 28px;
  height: 28px;
  padding: 0;
  border-radius: 50%;
  font-size: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.btn-reverse { background: #f39c12; color: white; }
.btn-optimize { background: #1abc9c; color: white; }
.btn-export { background: #34495e; color: white; }
.btn-publish { background: #3498db; color: white; }
.btn-execute { background: #2ecc71; color: white; }
.btn-stop { background: #e74c3c; color: white; }

@media (max-width: 768px) {
  .map-canvas {
    width: 100%;
    height: auto;
  }
  
  .form-fields {
    flex-direction: column;
    align-items: stretch;
  }
  
  .list-header, .list-row {
    flex-direction: column;
  }
  
  .col-index, .col-x, .col-y, .col-z, .col-action {
    width: auto;
    padding: 8px;
    border-bottom: 1px solid #e0e0e0;
    text-align: left;
  }
  
  .col-action {
    justify-content: flex-start;
  }
  
  .waypoint-batch-actions,
  .trajectory-actions {
    flex-direction: column;
  }
  
  .send-controls {
    flex-direction: column;
  }
  
  .trajectory-options {
    justify-content: center;
  }
  
  .status-info {
    flex-direction: column;
    gap: 10px;
  }
  
  .map-status {
    flex-direction: column;
    gap: 10px;
  }
}
</style>